<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  

  
  <title>面试全集 | 雁过留声</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="集合 java 有哪些常用容器，哪些是同步容器，哪些是并发容器答案: ArrayList,LinkedList,HashMap,hashSet,treeSet;CopyOnWriteArrayList,HashTable,ConcurrentHashMap, ArrayList 插入和 LinkedList 插入时间复杂度插入    查找    删除arrayList       o(1)">
<meta property="og:type" content="article">
<meta property="og:title" content="面试全集">
<meta property="og:url" content="http://yanglf007.gitee.io/blog/2020/08/01/%E9%9D%A2%E8%AF%95%E5%85%A8%E9%9B%86/index.html">
<meta property="og:site_name" content="雁过留声">
<meta property="og:description" content="集合 java 有哪些常用容器，哪些是同步容器，哪些是并发容器答案: ArrayList,LinkedList,HashMap,hashSet,treeSet;CopyOnWriteArrayList,HashTable,ConcurrentHashMap, ArrayList 插入和 LinkedList 插入时间复杂度插入    查找    删除arrayList       o(1)">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="http://chuantu.xyz/t6/740/1596546954x1033347913.jpg">
<meta property="og:image" content="https://images.gitee.com/uploads/images/2020/0810/113838_acbcc8db_1207148.jpeg">
<meta property="og:image" content="https://images.gitee.com/uploads/images/2020/0810/113838_92aea2f6_1207148.jpeg">
<meta property="article:published_time" content="2020-08-01T06:43:37.632Z">
<meta property="article:modified_time" content="2020-08-26T13:08:10.001Z">
<meta property="article:author" content="yanglf007">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://chuantu.xyz/t6/740/1596546954x1033347913.jpg">
  
    <link rel="alternate" href="/blog/atom.xml" title="雁过留声" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  
<link rel="stylesheet" href="/blog/css/style.css">

<meta name="generator" content="Hexo 4.2.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/blog/" id="logo">雁过留声</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/blog/">Home</a>
        
          <a class="main-nav-link" href="/blog/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/blog/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://yanglf007.gitee.io/blog"></form>
      </div>
    </div>
  </div>
</header>
      <div class="outer">
        <section id="main"><article id="post-面试全集" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/blog/2020/08/01/%E9%9D%A2%E8%AF%95%E5%85%A8%E9%9B%86/" class="article-date">
  <time datetime="2020-08-01T06:43:37.632Z" itemprop="datePublished">2020-08-01</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="article-title" itemprop="name">
      面试全集
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h3 id="集合"><a href="#集合" class="headerlink" title="集合"></a>集合</h3><ol>
<li>java 有哪些常用容器，哪些是同步容器，哪些是并发容器<br>答案: ArrayList,LinkedList,HashMap,hashSet,treeSet;<br>CopyOnWriteArrayList,HashTable,ConcurrentHashMap,</li>
<li>ArrayList 插入和 LinkedList 插入时间复杂度<pre><code>插入    查找    删除</code></pre>arrayList       o(1)    o(1)<br>linkedList      o(1)    o(n)</li>
</ol>
<ol start="3">
<li>hashMap 什么情况下回扩容，或者哪些操作会扩容</li>
</ol>
<p>HashMap 默认大小16，加载因子0.75 ，每次扩容2，为2的原因是 hash%length==hash&amp;(length-1)的前提是length是2的n次方<br>4. hashMap put方法执行过程<br>第一步. 进来先检查 数组是否为空，为空的话先创建一个大小为16的数组<br>第二步. 取key的hash值与数组仓库取余得到坐标i，看i所在位置是否为空，如果为空，直接构建一个node<br>第三步. 检查i所在为啥是否是树节点，如果不是树节点，那就是链表，循环遍历链表，插入到最后一个节点，检查链表长度是否达到数的阈值8，（小于6退化成链表）<br>        达到了就进行树化，在树化的时候继续检查，如果table的长度小于64，直接进行扩容，不需要树化，否则  链表转换为一棵红黑树，<br>        如果是treenode节点</p>
<ol start="5">
<li><p>hashMap检测到hash冲突，插入链表的末尾还是开头<br>Node 结构 泛型类型key 和 value, final 修饰的 int 类型 的 hash ,next下一个node节点<br>TreeNode 结构 左节点，右节点，父节点，前节点，后节点（继承来的）<br>插入链表末尾，node 是一个单向链表</p>
<p>1.7插入元素到单链表中采用头插入法，1.8采用的是尾插入法。<br>HashMap在jdk1.7中采用头插入法，在扩容时会改变链表中元素原本的顺序，以至于在并发场景下导致链表成环的问题。而在jdk1.8中采用尾插入法，在扩容时会保持链表元素原本的顺序，就不会出现链表成环的问题了。</p>
</li>
</ol>
<ol start="6">
<li>1.8红黑树，红黑树特点，为什么用红黑树，不用avl树和 b树<br>avl树（平衡二叉树） 插入慢，查询快，<br>红黑树特点：<br>一个节点必须是红色或者黑色<br>根节点必须是黑色<br>如果一个节点是红色，则子节点必须是黑色<br>一个节点到空引用的节点必须包含相同数量的黑色节点，红色节点不受影响<br>插入点默认为红色<br>困难点：插入一个项是要维持树的高度，需要进行树的变形    </li>
</ol>
<p>左旋， 大儿子变父亲，小孙子变儿子<br>左旋旋转点为父亲节点，右旋旋转点为爷爷</p>
<pre><code>旋转和颜色变换规则:所有插入的点默认为红色&quot;,
1.变颜色的情况:当前结点的父亲是红色，且它的祖父结点的另一个 子结点&quot;,
也是红色。( 叔叔结点) :&quot;,
(1)把父节点设为黑色&quot;,
( 2 )把叔叔也设为黑色&quot;,
( 3 )把祖父也就是父亲的父亲设为红色(爷爷)&quot;,
( 4 )把指针定义到祖父结点设为当前要操作的.(爷爷)分析的点变换的规则&quot;,
2.左旋:当前父结点是红色，叔叔是黑色的时候,且当前的结点是右子树。左旋&quot;,
以父结点作为左旋。&quot;,
3.右旋:当前父结点是红色，叔叔是黑色的时候,且当前的结点是左子树。右旋&quot;,
(1)把父结点变为黑色&quot;,
I&quot;,
(2)把祖父结点变为红色(爷爷)&quot;,
( 3 )以祖父结点旋转(爷爷) TreeMap JDK1.8大学给小学弟( )&quot;,</code></pre><ol start="7">
<li>ConcurrentHashMap </li>
</ol>
<p>ConcurrentHashMap 初始化，调用put的时候进行初始化，先检查map是否为空，如果为空检查 进入一个while循环，检查sizeCtl大小,如果sizeCtl&lt;0<br> 表示有线程正在初始化table,调用thread.yield()让出线程，如果&gt;=0， 通过cas操作，将sizeCtl 设置为-1，然后进行初始化，扩容阈值设置table长度的0.75</p>
<p>tableAt(),casTableAt() setTableAt() 三个原子操作</p>
<p>锁是通过synchronized 锁住hash桶中的头结点，相比Segment优势是，锁的颗粒度小，并且由jvm进行管理锁升级过程，无锁，偏向锁，轻量级锁，重量级锁</p>
<p>put过程：<br>1 检查key 和 value 是否为空<br>2 spread（）方法转换hash值，全部转为大于0的值，<br>3 启动一个无限循环，判断table是否为空，为空进行table初始化<br>4 调用tabAt原子操作查看 需要放入的槽位置是否为空，如果为空，调用casTabAt 进行设置<br>5 如果不为空，检查hash值是否等于-1 （MOVE）,-1表示是一个ForwardingNode，是一个临时节点，在扩容时才会出现，不存储数据，如果就的hash桶<br>中数据已经移到新的hash桶中，就放一个ForwardingNode，指向新的table数组，遇到读的时候在新table中查找，遇到写的时候帮忙扩容<br>如果 hash大于0，使用synchronized 对头部结点进行加锁，然后再判断是链表还是TreeBin,来添加到链表后面，还是加在红黑树树，</p>
<p>get过程<br>1 spread（）转换hash值，调用tableAt()获取结点，如果为空，返回空，<br>不为空时，判断当前结点是否是要取得值（hash相等，并行key相等），如果是返回<br>如果当前hash值小于0，当为-1时，表示hash槽进行扩容，调用ForwardingNode 的find方法，找到新的table,在新table中寻找<br>当为-2时表示是一个treein,调用treeBin 的find方法进行查找<br>否则表示是一个链表，循环遍历，判断key是否相同就行</p>
<p>并发扩容过程<br><a href="https://blog.csdn.net/ZOKEKAI/article/details/90051567" target="_blank" rel="noopener">https://blog.csdn.net/ZOKEKAI/article/details/90051567</a><br>putval()调用完成的最后调用addCount() 方法<br>利用 CounterCell 做了一个分段设计，就是通过一次cas更新不成功的话，计算当前线程所在的位置，更新这个位置的值，通过for循环和cas更新<br>CounterCell 被@sun.misc.Contended 修饰，防止伪共享<br>加起来sum就是所有元素的个数，如果大于 sizeCtl（数组长度*加载因子），<br>如果当前的数据sizeCtl 小于0，表示有线程在进行扩充<br>最终调用 transfer() 进行扩容<br>每个线程扩容的桶数与cpu核心数有关，核心越多，单个线程处理桶数越少，每个线程最少分配16个桶<br>新建一个node节点的数组，大小是当前table的两倍，作为nextTable</p>
<p>size()<br>size是由sumCount方法决定，技术counterCell 数组之和</p>
<ol start="8">
<li><p>hashMap怎么解决hash冲突</p>
</li>
<li><p>arrayList 扩容<br>答： 每次增加元素时会检查数组容量，<br>首先需要的大小和默认大小10 比较取大的，<br>如果需要的最小长度，大于当前数组长度，进行数组扩容<br>需要的最小长度 和 数组长度的1.5倍比较，如果最小值比1.5倍大，扩容的大小就是最小长度， 或者就是数组的1.5倍扩容<br>此外，还会坚持是否大于默认最大值，Integer.MAX_VALUE - 8 （原因是一些虚拟机会保存数组的头信息）, 如果大于，扩容大小改为Integer.MAX_VALUE</p>
</li>
</ol>
<p>10 queue 和 deque 区别<br>queue 是 deque的接口，是一个先进先出队列 实现有 DelayQueue，<br>deque 是一个双向队列，实现由LinkedList</p>
<p>11 Collections.synchronizedHashMap(new HashMap()) 如何实现线程安全<br>返回的是 SynchronizedMap ，在调用构造方法的时候，把当前对象作为互斥量，调用插入，查询是，synchronized 对当前对象加锁，同一个线程的当前对象才能访问</p>
<ol start="12">
<li>StringBuffer 和StringBuilder<br>StringBuffer是线程安全的，所有公开方法加synchronized，所以性能不好，</li>
</ol>
<h3 id="io"><a href="#io" class="headerlink" title="io"></a>io</h3><h3 id="java-并发类-juc"><a href="#java-并发类-juc" class="headerlink" title="java 并发类 juc"></a>java 并发类 juc</h3><ol>
<li><p>讲一讲 AtomicInteger，为什么用cas,而不是 syschronized ,AtomicReference</p>
</li>
<li><p>java锁有哪些类，以及区别</p>
</li>
<li><p>LongAddr原理<br>内部维护了一个cell 数组，通过cas去更新值，如果更新成功推出，否则多个线程只有一个成功，其他失败，失败的找到当前线程在cell 中的坐标，通过循环 和cas<br>更新坐标的值，最后调用sum方法是计算各个桶数据之和<br><a href="https://blog.csdn.net/wolf_love666/article/details/87693771" target="_blank" rel="noopener">https://blog.csdn.net/wolf_love666/article/details/87693771</a></p>
</li>
<li><p>LongAdder如何解决缓存行问题<br>一个缓存行一般大小64字节,long类型8个字节，更新当前值导致其他值失效，同样需要从主内存加载，称之为伪共享<br>早期是定义几个无用变量放在一起，<br>之和可以通过sun.mis.contended注解解决</p>
</li>
</ol>
<ol start="6">
<li>可重入锁reentrantLock实现原理<br>调用tryAcquire 的时候会检查 state是否等于0 ,如果不等于0 ,判断当前独占线程是否等于当前线程,如果等于就在状态上加一</li>
</ol>
<p>加锁过程 reentrantLock 默认非公平锁 </p>
<p>0)调用lock,一次cas修改状态,失败后调用acquire()<br>acquire()加锁过程分三步:<br>1)tryAcquire()<br>如果状态是0,通过一次cas修改状态,如果修改成功,将独占线程设置为当前线程<br>2)addWaiter()<br>获取锁没有成功的时间就加入等待队列,node节点链表,加入末尾<br>enq；通过cas将当前结点设置为尾结点<br>3)acquireQueued()<br>如果当前节点的前一个节点是head节点,再次tryAcquire,试图获取锁<br>调用parkAndCheckInterrupt来达到阻塞效果 </p>
<p>公平锁和非公平锁的主要区别在于：<br>非公平锁上来就cas修改状态，如果是0，就可以修改成功获取锁<br>公平锁，如果是0 ，会判断是否有前驱结点，如果有，就老老实实排队</p>
<p>去锁过程</p>
<p>1) 状态减一,如果状态为0,将独占线程置为空<br>2) 如果状态为0,调用unparkSuccessor(),唤醒头节点的下一节点LockSupport.unpark(s.thread);</p>
<h3 id="多线程"><a href="#多线程" class="headerlink" title="多线程"></a>多线程</h3><ol>
<li><p>线程池工作原理，几个重要参数作用，阻塞队列作用</p>
</li>
<li><p>说一下对Synchronized 和lock的理解，说说他们之间区别<br>要点：乐观悲观，锁升级过程，静态代码块，同步代码块区别， lock的几个实现，实现原理 aqs</p>
</li>
</ol>
<p>AbstractQueuedSynchronizer 类如其名，抽象的队列式的同步器，AQS 定义了一套多线程访问<br>共享资源的同步器框架，许多同步类实现都依赖于它，如常用的<br>ReentrantLock/Semaphore/CountDownLatch</p>
<p>synchronized 底层依赖操作系统 Mutex Lock实现，是一个可重入锁<br>操作系统实现线程直接切换，需要从用户态转换到核心态，成本高<br><img src="http://chuantu.xyz/t6/740/1596546954x1033347913.jpg" alt="avator"></p>
<p>锁粗化：将很多次锁的请求合并成一次，以降低短时间内大量锁请求，释放带来的性能损耗</p>
<figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">for(int i=0;i&lt;size;i++)&#123;</span><br><span class="line">    synchronized(lock)&#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>锁消除 编译器级别的事情，编译器发现如果不可能被共享的对象，可以消除这些对象的锁操作</p>
<p>synchronized 锁升级过程</p>
<p>只有一个线程的情况</p>
<p>1,检查锁标识位,markword最后两位 01 ,标识无锁和偏向锁<br>前一位 如果是0 ,表示无锁,将无锁升级成偏向锁,cas操作,将对象头中的hashCode换成当前线程ID<br>第二次进入的时候检查是否是偏向锁,如果是偏向锁,检查对象头的线程ID是否是当前ID,如果是当前ID,则获得锁</p>
<p>有多个线程<br>A线程拿到偏向锁, 线程B无锁状态,<br>线程B到达synchronized代码块,将无锁升级成偏向锁,cas替换对象头中的hashCode为当前线程ID,成功则获取对象锁<br>失败:开始出现锁竞争,撤销偏向锁,到达安全点,暂停执行原偏向锁线程<br>A开始升级成轻量级锁,向线程栈中分配锁记录,copy对象头中markword 到锁记录中,对象头中保存锁记录指针,锁标志位变为00,唤醒A线程,从安全点开始执行,开始轻量级锁解锁<br>B线程锁升级位轻量级锁,在当前线程栈中分配锁记录,将对象头markword copy到线程锁记录中,cas参数修改对象头锁记录指针,指向当前线程锁记录<br>失败就进行自旋,达到一定次所后升级成重量级说,锁标识位改为10,进入互斥量(mutex)队列挂起等待</p>
<p>轻量级解锁:cas操作,对比对象头中markword中锁指针是否是当前线程,当前线程的锁记录是否和对象头中markword一致, 成功则获取锁,失败升级成重量级锁进行等待</p>
<p>vilitate 关键字</p>
<p>内存屏障<br> (1）在每一个volatile写操作前面插入一个StoreStore屏障。这确保了在进行volatile写之前前面的所有普通的写操作都已经刷新到了内存。<br>（2）在每一个volatile写操作后面插入一个StoreLoad屏障。这样可以避免volatile写操作与后面可能存在的volatile读写操作发生重排序。<br>（3）在每一个volatile读操作后面插入一个LoadLoad屏障。这样可以避免volatile读操作和后面普通的读操作进行重排序。<br>（4）在每一个volatile读操作后面插入一个LoadStore屏障。这样可以避免volatile读操作和后面普通的写操作进行重排序。</p>
<p>写操作前,在前后增加屏障<br>读操作后,在后面加两个屏障</p>
<ol start="3">
<li><p>如何保证线程安全</p>
</li>
<li><p>线程池创建和运行过程</p>
</li>
<li><p>threadLocal</p>
</li>
<li><p>同步，异步，并发，并行区别</p>
</li>
</ol>
<p>并发只具有处理多个任务的能力，不一定同时进行<br>并行是同时处理多个任务的能力</p>
<ol start="8">
<li>thread 方法<br>Thread.yield()；当前线程由执行状态变成就绪状态，让出cpu时间，在下一个程序执行时，当前线程可能被执行，也可能不被执行<br>Thread.currentThread()；获取当前线程<br>sleep(); 休眠一段时间，不会让出锁；<br>start();线程启动入口，会将当前线程加入threadGroup中，调用native　start0 方法启动一个线程<br>run();实现runable 接口，必须实现run方法，直接调用相当于调用普通方法<br>stop(); 以过期，线程不安全 UnsupportedOperationException</li>
</ol>
<p>interrupt() 给调用的线程设置一个中断标识位,遇到sleep,wait会中断,报InterruptedException异常<br>interrupted() 重置中断标识位,被中断后重置,不会抛出异常<br>isInterrupted() 判断线程的中断标识位<br>join() 阻塞执行代码的线程,等待join的调用线程执行完成,内部实现是object.wait(),线程执行完成会有一个notify_all</p>
<ol start="9">
<li><p>thread的start方法能调用两次吗<br>不能，第二次报java.lang.IllegalThreadStateException，启动时会检查状态是否为0<br>start是一个同步方法，启动线程时会将当前线程加入到ThreadGroup中，调用native start0方法</p>
</li>
<li><p>thread 状态有哪些<br>NEW 新建<br>RUNNABLE 可以运行<br>BLOCKED 阻塞 线程调用object.wait thread.join LockSupport.park 的时候变成 WAITING<br>WAITING<br>TIMED_WAITING<br>TERMINATED</p>
</li>
</ol>
<p><img src="https://images.gitee.com/uploads/images/2020/0810/113838_acbcc8db_1207148.jpeg" alt="avator"></p>
<ol start="11">
<li><p>object 方法<br>wait(); 当前线程休眠，让出对象锁，让其他持有当前对象的锁开始执行，直到有人唤醒,唤醒后需要重新获取锁<br>notify();唤醒其他休眠线程,不会让出cpu，会继续执行，被唤醒的线程需要重新获取锁</p>
</li>
<li><p>LockSupport.park</p>
<p>线程池 execute执行逻辑</p>
<pre><code>1,检查执行命令是否为空,为空报空指针异常
2,如果当前工作线程数,小于核心线程数,开启一个工作线程执行当前命令
3,如果线程池状态是运行状态,开始向队列中添加命令
    如果添加失败,不能进入队列,尝试开启一个新线程,开启失败时报拒绝服务
4,如果添加成功,进行双重校验,如果当前线程池状态不是运行中,则从队列中移出命令,报拒绝服务

添加工作线程的逻辑
1,检查如果不是运行中
2,开启一个循环 如果工作线程数大于 最大核心线程数,或者线程池最大线程数 直接返回false,添加线程失败
3,通过cas更新工作线程数,更新成功退出循环,更新失败,继续重新    cas更新
4,创建一个Worker,将当前命令commond作为构造方法的参数传递进去,并且从线程工厂拿到一个新线程 (ThreadFactory) ,默认是 Executors.defaultThreadFactory()
5,从worker中拿到线程,如果线程不为空,ReentrantLock 加锁 ,将worker加入到hashset的线程队列中,然后释放锁
6,如果添加线程成功,调用start方法执行线程,因为worker试下了runnble接口,实际上是开启线程执行run方法,实际就是执行 runWorker方法
7,后面看不懂了 java.util.concurrent.ThreadPoolExecutor#runWorker

execute 和 submit 区别
submit 提交线程的时候会返回一个Future对象,内部执行的还是execute方法

创建线程的构造方法
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler(AbortPolicy)</span><br></pre></td></tr></table></figure></code></pre></li>
</ol>
<pre><code>DefaultThreadFactory 工厂模式

  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> Thread <span class="title">newThread</span><span class="params">(Runnable r)</span> </span>&#123;</span><br><span class="line">      Thread t = <span class="keyword">new</span> Thread(group, r,namePrefix + threadNumber.getAndIncrement(),<span class="number">0</span>);</span><br><span class="line">      <span class="keyword">if</span> (t.isDaemon())</span><br><span class="line">          t.setDaemon(<span class="keyword">false</span>);</span><br><span class="line">      <span class="keyword">if</span> (t.getPriority() != Thread.NORM_PRIORITY)</span><br><span class="line">          t.setPriority(Thread.NORM_PRIORITY);</span><br><span class="line">      <span class="keyword">return</span> t;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure></code></pre><p>  FutureTask原理</p>
<pre><code>private static final int NEW          = 0;
private static final int COMPLETING   = 1;
private static final int NORMAL       = 2;
private static final int EXCEPTIONAL  = 3;
private static final int CANCELLED    = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED  = 6;</code></pre><p>设置结果前通过cas设置为COMPLETING<br>设置结果后通过cas设置为NORMAL</p>
<p>LockSupport.unpark(t);</p>
<p>FutureTask调用 get()方法的时候，如果状态小于COMPLETING,调用awaitDone()方法，</p>
<p>awaitDone()中判断是否有等待时间，结束时间就是当前时间加等待时间<br>进入循环体，如果超时，从等待队列中移除，返回当前状态<br>如果状态是COMPLETING，就调用 Thread.yield(),休眠，让出当前cpu,<br>如果状态COMPLETING，就是NORMAL，就结束循环返回状态</p>
<p>调用report(),返回数据，如果状态是NORMAL，正常返回，否则抛出异常</p>
<p>13 创建线程池方法<br>Executors.newScheduledThreadPool() 每隔多少时间执行一次，<br>scheduleAtFixedRate 两次开始间隔时间<br>scheduleWithFixedDelay 第一次执行完，到第二次执行时间<br>Executors.newFixedThreadPool(1);<br>Executors.newSingleThreadExecutor(); 发送异常后重启一个线程来执行原任务<br>Executors.newCachedThreadPool();</p>
<ol start="14">
<li>线程状态<br>new<br>Runnable<br>Running运行中<br>Blocked 阻塞 synchronized会导致线程进入block状态<br>WAITING 等待 Object.wait会导致线程进入wait状态<br>TIMED_WAITING Thread.sleep(0)<br>TERMINATED 终止</li>
</ol>
<ol start="15">
<li><p>线程异常退出源码分析<br><a href="https://www.cnblogs.com/wang-meng/p/10588637.html" target="_blank" rel="noopener">https://www.cnblogs.com/wang-meng/p/10588637.html</a></p>
<h3 id="反射"><a href="#反射" class="headerlink" title="反射"></a>反射</h3></li>
<li><p>java反射原理，注解原理</p>
</li>
<li><p>反射的作用是什么</p>
</li>
<li><p>Thread方法有哪些<br>Thread.sleep(0)<br>Thread.join<br>thread.notify()<br>thread.notifyAll()<br>thread.currentThread()<br>thread.isAlive()<br>thread.isDaemon()<br>thread.setDaemon()<br>thread.setPriority()<br>thread.getPriority()</p>
</li>
<li><p>死锁产生的条件<br>互斥条件：进程要求对所分配的资源进行排它性控制，即在一段时间内某资源仅为一进程所占用。<br>请求和保持条件：当进程因请求资源而阻塞时，对已获得的资源保持不放。<br>不剥夺条件：进程已获得的资源在未使用完之前，不能剥夺，只能在使用完时由自己释放。<br>环路等待条件：在发生死锁时，必然存在一个进程–资源的环形链。</p>
</li>
</ol>
<p>解决死锁：</p>
<ol>
<li>一次性获取所有资源</li>
<li>获取部分资源，等不到其他资源，则释放掉已经得到的资源</li>
<li>资源有序分配</li>
</ol>
<p>18 线程池原理</p>
<p>线程池做的工作主要是控制运行的线程的数量，处理过程中将任务放入队列，然后在线程创建后<br>启动这些任务，如果线程数量超过了最大数量超出数量的线程排队等候，等其它线程执行完毕，<br>再从队列中取出任务来执行。他的主要特点为：线程复用；控制最大并发数；管理线程</p>
<ol start="19">
<li>线程池状态<br>private static final int RUNNING    = -1 &lt;&lt; COUNT_BITS;<br>private static final int SHUTDOWN   =  0 &lt;&lt; COUNT_BITS;<br>private static final int STOP       =  1 &lt;&lt; COUNT_BITS;<br>private static final int TIDYING    =  2 &lt;&lt; COUNT_BITS;<br>private static final int TERMINATED =  3 &lt;&lt; COUNT_BITS;</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">execute</span><span class="params">(Runnable command)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (command == <span class="keyword">null</span>)</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">       </span><br><span class="line">        <span class="keyword">int</span> c = ctl.get();</span><br><span class="line"><span class="comment">//当前工作线程小于核心线程</span></span><br><span class="line">        <span class="keyword">if</span> (workerCountOf(c) &lt; corePoolSize) &#123;</span><br><span class="line">            <span class="keyword">if</span> (addWorker(command, <span class="keyword">true</span>))</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            c = ctl.get();</span><br><span class="line">        &#125;</span><br><span class="line"><span class="comment">//正在运行时，工作队列中添加命令</span></span><br><span class="line">        <span class="keyword">if</span> (isRunning(c) &amp;&amp; workQueue.offer(command)) &#123;</span><br><span class="line">            <span class="keyword">int</span> recheck = ctl.get();</span><br><span class="line">            <span class="keyword">if</span> (! isRunning(recheck) &amp;&amp; remove(command))</span><br><span class="line">                reject(command);</span><br><span class="line"><span class="comment">//当前工作线程数为0</span></span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span> (workerCountOf(recheck) == <span class="number">0</span>)</span><br><span class="line">                addWorker(<span class="keyword">null</span>, <span class="keyword">false</span>);</span><br><span class="line">        &#125;</span><br><span class="line"><span class="comment">//开启一个非核心线程</span></span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (!addWorker(command, <span class="keyword">false</span>))</span><br><span class="line">            reject(command);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>线程池原理<br><img src="https://images.gitee.com/uploads/images/2020/0810/113838_92aea2f6_1207148.jpeg" alt="avator"><br>核心线程 ：固定线程数 可闲置 不会被销毁 ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true时，keepAliveTime同样会作用于核心线程<br>非核心线程数：非核心线程闲置时的超时时长，超过这个时长，非核心线程就会被回收</p>
<p>20 阻塞队列原理<br>不能插入空值</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">put</span><span class="params">(E e)</span> <span class="keyword">throws</span> InterruptedException </span>&#123;</span><br><span class="line">       <span class="keyword">if</span> (e == <span class="keyword">null</span>) <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">       <span class="keyword">int</span> c = -<span class="number">1</span>;</span><br><span class="line">       Node&lt;E&gt; node = <span class="keyword">new</span> Node&lt;E&gt;(e);</span><br><span class="line">       <span class="keyword">final</span> ReentrantLock putLock = <span class="keyword">this</span>.putLock;</span><br><span class="line">       <span class="keyword">final</span> AtomicInteger count = <span class="keyword">this</span>.count;</span><br><span class="line">       putLock.lockInterruptibly();</span><br><span class="line">       <span class="keyword">try</span> &#123;</span><br><span class="line">           <span class="keyword">while</span> (count.get() == capacity) &#123;</span><br><span class="line">               notFull.await();</span><br><span class="line">           &#125;</span><br><span class="line">           enqueue(node);</span><br><span class="line">           c = count.getAndIncrement();</span><br><span class="line">           <span class="keyword">if</span> (c + <span class="number">1</span> &lt; capacity)</span><br><span class="line">               notFull.signal();</span><br><span class="line">       &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">           putLock.unlock();</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">if</span> (c == <span class="number">0</span>)</span><br><span class="line">           signalNotEmpty();</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<p>add offer put 区别<br>remove poll,take<br>没有添加成功，抛异常，offer没有添加成功返回false,put会阻塞<br>满的队列未满时用 notFull条件锁唤醒</p>
<p>空的队列未空时 notEmpty条件锁唤醒</p>
<ol start="21">
<li>condition锁方法<br>await<br>await<br>awaitNanos<br>awaitUninterruptibly<br>awaitUntil<br>signal<br>signalAll</li>
</ol>
<h4 id="编译"><a href="#编译" class="headerlink" title="编译"></a>编译</h4><h4 id="类加载机制"><a href="#类加载机制" class="headerlink" title="类加载机制"></a>类加载机制</h4><p>加载 读取class文件，在内存中生成一个类的class对象<br>验证 确保class文件的字节流符合虚拟机要求<br>准备 为类变量分配内存空间，初始值为0，<br>解析 将常量池中的符号引用替换成直接引用<br>初始化 开始执行java代码，<br>使用<br>卸载</p>
<h4 id="双亲委派模型"><a href="#双亲委派模型" class="headerlink" title="双亲委派模型"></a>双亲委派模型</h4><p>当一个类收到加载请求，首先不会直接加载这个类，而是委派给父类去完成，如果父类不能加载，子类加载器才会尝试加载</p>
<p>BootstrapClassLoader  java_home/jre/lib<br>ExtClassLoader java_home/jre/lib/ext<br>AppClassLoader 应用程序类加载器 加载classpath<br> 用户自定义的类</p>
<h4 id="如何打破双亲委派"><a href="#如何打破双亲委派" class="headerlink" title="如何打破双亲委派"></a>如何打破双亲委派</h4><h4 id="为什么用双亲委派"><a href="#为什么用双亲委派" class="headerlink" title="为什么用双亲委派"></a>为什么用双亲委派</h4><h4 id="jvm内存模型"><a href="#jvm内存模型" class="headerlink" title="jvm内存模型"></a>jvm内存模型</h4><h4 id="类实例化顺序"><a href="#类实例化顺序" class="headerlink" title="类实例化顺序"></a>类实例化顺序</h4><h3 id="框架"><a href="#框架" class="headerlink" title="框架"></a>框架</h3><h4 id="spring"><a href="#spring" class="headerlink" title="spring"></a>spring</h4><ol>
<li><p>springmvc 处理全流程</p>
</li>
<li><p>spring 容器初始化过程，ioc加载过程(<strong>重要</strong>）</p>
</li>
<li><p>spring 单例bean注入过程</p>
</li>
<li><p>spring bean循环依赖</p>
</li>
<li><p>spring中事物的隔离级别</p>
</li>
</ol>
<h4 id="dubbo"><a href="#dubbo" class="headerlink" title="dubbo"></a>dubbo</h4><ol>
<li>dubbo中rpc如何实现</li>
<li>自己实现rpc，应该怎么做</li>
<li>dubbo 的服务注册和发现</li>
</ol>
<h4 id="netty"><a href="#netty" class="headerlink" title="netty"></a>netty</h4><ol>
<li>netty优点，原理</li>
</ol>
<h4 id="mybatis"><a href="#mybatis" class="headerlink" title="mybatis"></a>mybatis</h4><ol>
<li><p>mybatis #和$ 的区别</p>
</li>
<li><p>mybatis dao和xml怎么建立关系</p>
</li>
</ol>
<h3 id="mysql"><a href="#mysql" class="headerlink" title="mysql"></a>mysql</h3><ol>
<li><p>什么情况下导致不会使用索引</p>
</li>
<li><p>数据库索引，底层怎么实现，为什么要用b树索引,b+树大致结构</p>
</li>
<li><p>谈一谈数据库乐观锁和悲观锁</p>
</li>
<li><p>mysql 隔离级别</p>
</li>
<li><p>可以重复读实现原理（mvcc机制） 多版本并发控制</p>
</li>
<li><p>mysql用什么存储引擎，存储引擎用的什么数据结构，有哪些优缺点，怎么使用<br>b+树，为什么不用b树，不能范围查询，阶是根据缓存也大小16k和单个索引大小共同确定的， b树分裂，中间值拿到父节点，b+树分裂，最大值存到父节点，</p>
</li>
<li><p>mysql有哪些锁<br>一、按照对数据操作的锁粒度来分：行级锁、表级锁、页级锁、间隙锁</p>
</li>
</ol>
<p>1 行级锁</p>
<p>2 表级锁</p>
<p>3 页级锁</p>
<p>二、按照锁的共享策略来分：共享锁、排他锁、意向共享锁、意向排他锁<br>innodb的意向锁有什么作用？<br>三、从锁策略上分：乐观锁和悲观锁<br>四、其他：自增锁<br>自增锁（AUTO-INC锁）</p>
<ol start="8">
<li>分库分表<br><a href="https://blog.csdn.net/qq_39416311/article/details/86730483" target="_blank" rel="noopener">https://blog.csdn.net/qq_39416311/article/details/86730483</a><br>分库分表带来的问题:<br>主键还是自增,生成一个业务组件code,<br>code有业务域和ID组成,这个ID通过redis自增实现的(Incr),</li>
</ol>
<p>其他方案,<br>雪花算法,第一位符合位 ,41位时间截,10 机器序号,12位序列,没毫秒可以产生4096个ID<br>根据步长设置自增</p>
<h3 id="redis"><a href="#redis" class="headerlink" title="redis"></a>redis</h3><ol>
<li><p>MongoDB 和 redis适用哪些场景</p>
</li>
<li><p>分布式事物TCC服务设计</p>
</li>
<li><p>redis 和 memcache 有什么区别，redis为什么相比memcache有优势</p>
</li>
<li><p>谈谈分布式锁，以及分布式全局唯一ID的实现和比较</p>
</li>
<li><p>redis 怎么实现分布式锁</p>
</li>
<li><p>redis 数据结构</p>
</li>
<li><p>缓存穿透，缓存雪崩，缓存击穿</p>
</li>
<li><p>redis 为什么那么快<br>单线程，内存，io多路复用（深入）</p>
</li>
<li><p>缓存的实现原理，设计缓存要注意什么</p>
<p>  缓存是在内存或数据库中间存储的一道门槛，为了查询快速，要注意数据一致性<br> 1）缓存和db同时更新数据，不在同一个事物，且没有补偿机制<br> 2）没有查到缓存导致数据库被打爆</p>
</li>
</ol>
<ol start="10">
<li><p>redis服务器怎么扩容</p>
</li>
<li><p>redis失效key清除策略</p>
</li>
<li><p>redis怎么实现附件的人 （空间索引）</p>
</li>
<li><p>热点数据失效问题</p>
</li>
<li><p>先删除缓存，还是先更新数据库</p>
</li>
<li><p>redis cluster 如何试下高可用<br>集群是一个由多个主从节点群组成的分布式服务器群，它具有复制、高可用和分片特性。Redis cluster集群不需要sentinel哨兵也能完成节点移除和故障转移的功能<br>集群模式<br>redis cluster集群需要至少要三个master节点，这里搭建三个master节点，并且给每个master再搭建一个slave节点，总共6个redis节点，</p>
</li>
</ol>
<p>哨兵模式是一种特殊的模式，首先Redis提供了哨兵的命令，哨兵是一个独立的进程，作为进程，它会独立运行。其原理是哨兵通过发送命令，等待Redis服务器响应，从而监控运行的多个Redis实例<br>通过发送命令，让Redis服务器返回监控其运行状态，包括主服务器和从服务器。<br>当哨兵监测到master宕机，会自动将slave切换成master，然后通过发布订阅模式通知其他的从服务器，修改配置文件，让它们切换主机。<br>然而一个哨兵进程对Redis服务器进行监控，可能会出现问题，为此，我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控，这样就形成了多哨兵模式。<br>用文字描述一下故障切换（failover）的过程。假设主服务器宕机，哨兵1先检测到这个结果，系统并不会马上进行failover过程，仅仅是哨兵1主观的认为主服务器不可用，这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用，并且数量达到一定值时，那么哨兵之间就会进行一次投票，投票的结果由一个哨兵发起，进行failover操作。切换成功后，就会通过发布订阅模式，让各个哨兵把自己监控的从服务器实现切换主机，这个过程称为客观下线。这样对于客户端而言，一切都是透明的。</p>
<ol start="16">
<li><p>说说redis的持久化机制，为啥不能用redis做专门的持久化数据库存储<br>1) 容量限制<br>2) 数据容易丢失<br>3) 数据解构基于key-value,无法关联查询</p>
<h3 id="消息队列"><a href="#消息队列" class="headerlink" title="消息队列"></a>消息队列</h3></li>
<li><p>如何保证消息的可靠性</p>
</li>
<li><p>消息队列可靠性和最终一致性</p>
</li>
<li><p>消息队列如何防重复</p>
</li>
<li><p>rocketmq 事物机制，和持久化</p>
</li>
<li><p>什么是死信队列</p>
</li>
</ol>
<h3 id="分布式"><a href="#分布式" class="headerlink" title="分布式"></a>分布式</h3><ol>
<li><p>springCloud 常用组件</p>
</li>
<li><p>注册中心怎么保证自己高可用<br>要点：2pc选举过程，崩溃恢复，数据同步过程,两阶段提交（2PC），三阶段提交（3PC）以及它们的相关应用。</p>
</li>
<li><p>分布式系统如何保证数据一致性</p>
</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">InterceptorConfig</span> <span class="keyword">extends</span> <span class="title">WebMvcConfigurerAdapter</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> LoginContextInterceptor loginContextInterceptor;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> SecurityCheckInterceptor securityCheckInterceptor;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> PermissionCheckInterceptor permissionCheckInterceptor;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addInterceptors</span><span class="params">(InterceptorRegistry registry)</span> </span>&#123;</span><br><span class="line">        registry.addInterceptor(loginContextInterceptor).addPathPatterns(<span class="string">"/**"</span>);</span><br><span class="line">        registry.addInterceptor(securityCheckInterceptor).addPathPatterns(<span class="string">"/**"</span>);</span><br><span class="line">        registry.addInterceptor(permissionCheckInterceptor).addPathPatterns(<span class="string">"/**"</span>);</span><br><span class="line">        <span class="keyword">super</span>.addInterceptors(registry);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">拦截器实现 HandlerInterceptor</span><br><span class="line">HandlerExecutionChain 中会遍历所有的注册的拦截器</span><br></pre></td></tr></table></figure>
<h4 id="访问者模式（visitor）"><a href="#访问者模式（visitor）" class="headerlink" title="访问者模式（visitor）"></a>访问者模式（visitor）</h4><h3 id="linux"><a href="#linux" class="headerlink" title="linux"></a>linux</h3><ol>
<li>linux如何查看负载均衡<br>1）top命令<br>2）uptime 命令<br>3）cat /cat/proc/loadavg</li>
</ol>
<h3 id="操作系统"><a href="#操作系统" class="headerlink" title="操作系统"></a>操作系统</h3><ol>
<li>操作系统的页式存储</li>
</ol>
<h3 id="网络"><a href="#网络" class="headerlink" title="网络"></a>网络</h3><ol>
<li><p>http和https区别</p>
</li>
<li><p>http请求过程和原理</p>
</li>
<li><p>tcp连接的特点</p>
</li>
<li><p>tcp如何保证安全可靠</p>
</li>
<li><p>tcp为什么要三次握手</p>
</li>
<li><p>top的流量控制和拥堵控制</p>
</li>
<li><p>tcp/ip 五层协议是哪些，作用是什么</p>
</li>
<li><p>什么是TCP粘包？怎么解决这个问题</p>
</li>
<li><p>tcp心跳包，为什么不用keepAlive</p>
</li>
<li><p>TCP和UDP的区别<br>TCP是基于连接的，UDP是基于无连接的。 TCP是可靠的，保证数据的顺序和正确性，UDP不可靠，不保证数据的顺序和正确性。 TCP比UDP对系统资源要求更多</p>
</li>
</ol>
<h3 id="设计"><a href="#设计" class="headerlink" title="设计"></a>设计</h3><ol>
<li><p>从千万到亿的数据，会面临哪些问题，解决思路是什么</p>
</li>
<li><p>如何设计存储海量数据的存储系统</p>
</li>
<li><p>如果需要扩展某个功能，如何降低系统耦合度</p>
</li>
<li><p>如果针对某个功能进行优化，你会怎么设计和优化</p>
</li>
</ol>
<h3 id="学习能力"><a href="#学习能力" class="headerlink" title="学习能力"></a>学习能力</h3><ol>
<li><p>最近学的新技术</p>
</li>
<li><p>遇到的最大困难是什么，怎么解决的</p>
</li>
<li><p>读过什么书</p>
</li>
<li><p>平时开发遇到哪些技术问题，怎么解决</p>
</li>
</ol>
<h3 id="项目"><a href="#项目" class="headerlink" title="项目"></a>项目</h3><p>主要有哪些模块</p>
<h3 id="算法"><a href="#算法" class="headerlink" title="算法"></a>算法</h3><ol>
<li>二分搜索过程</li>
<li>快排时间复杂度（<strong>重要</strong>）</li>
<li>冒泡排序，快排，归并排序优缺点及优化</li>
<li>设计一个算法，实现两10g大文件在10m内存中，将两个大文件中重复的放进第三个文件</li>
<li>插入排序，选择排序</li>
<li>b+树</li>
<li>红黑树</li>
<li>二叉搜索树<br>前序遍历，中序遍历，后续遍历，是指父节点在前后中，中序遍历数据是有序的，复杂度等于树高log(n)</li>
</ol>
<p>b树 ，b+树</p>
<pre><code>二叉查找树，红黑树，B-Tree, B+Tree 的区别: 
二叉查找树:二叉搜索树，优点查找快，但是在某些情况下会退化成链表，它是所有
高效查找树的基础，如果不懂这个其他的也学不懂。根本性的东西，最好能自己手写出来。
红黑树:内存查找高效树，不适合大数据量也不适合磁盘存储的。具体的分析就是IO浪费以及读取资源浪费，还有
就是树的深度会很大。适合一些底层系统做内存运算
B- Tree:可以认为是B+Tree过度。只需要知道BTree就可以
B+Tree:最适合大数据的磁盘索引，经典的MySql,所有的数据都存在叶子节点。其他都是索引，增加了系统的稳定
性以及遍历以及查找效率
不同:关键字和Key值。数据存储的地方，双向链表。
M阶:这个由磁盘的页面大小决定，磁盘快和页内存都是4KB.我们的节点数也就是我们的M值应该要尽可能的跟他一
样。这样的好处就是为了我们一次刚好能全部拿出一个节点里面存的所有的数据。</code></pre><h3 id="docker"><a href="#docker" class="headerlink" title="docker"></a>docker</h3><ol>
<li>对docker、k8s的了解</li>
</ol>
<h3 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h3><ol>
<li>主从选举</li>
</ol>
<h3 id="注解"><a href="#注解" class="headerlink" title="注解"></a>注解</h3><p>元数据 注解的注解：Target，Retention<br>ElementType 包括 TYPE，FIELD，METHOD，PARAMETER，CONSTRUCTOR，<br>RetentionPolicy 包括<br> SOURCE，只保留在源码，如override<br> CLASS，保留到class,加载class时候被抛弃<br> RUNTIME 类加载后还会存在<br>2. 去重策略<br>布伦过滤器</p>
<p>docker 设置超级权限<br>docker run -d –name=”centos7” –privileged=true centos:7 /usr/sbin/init</p>
<p>jmap -heap pid 无法使用<br><a href="https://www.jianshu.com/p/0e5d8db8ed5e" target="_blank" rel="noopener">https://www.jianshu.com/p/0e5d8db8ed5e</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yanglf007.gitee.io/blog/2020/08/01/%E9%9D%A2%E8%AF%95%E5%85%A8%E9%9B%86/" data-id="ckgtnonp60011m8ul9gnl9w6u" class="article-share-link">Share</a>
      
      
    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/blog/2020/08/01/%E8%87%AA%E6%88%91%E4%BB%8B%E7%BB%8D/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          自我介绍
        
      </div>
    </a>
  
  
    <a href="/blog/2020/07/31/%E9%9C%80%E8%A6%81%E4%BA%86%E8%A7%A3/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title">需要了解</div>
    </a>
  
</nav>

  
</article>

</section>
        
          <aside id="sidebar">
  
    

  
    

  
    
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/10/">October 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/08/">August 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/07/">July 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/06/">June 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/05/">May 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/04/">April 2020</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/blog/2020/10/25/%E6%AF%8F%E6%97%A5%E5%AD%A6%E4%B9%A0/">每日学习</a>
          </li>
        
          <li>
            <a href="/blog/2020/10/12/mybatis-plus/">mybatis-plus</a>
          </li>
        
          <li>
            <a href="/blog/2020/08/30/%E7%A7%92%E6%9D%80%E7%B3%BB%E7%BB%9F/">秒杀系统</a>
          </li>
        
          <li>
            <a href="/blog/2020/08/29/elasticsearch%E7%9F%A5%E8%AF%86/">elasticsearch知识</a>
          </li>
        
          <li>
            <a href="/blog/2020/08/28/redis%E9%9D%A2%E8%AF%95/">redis面试</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2020 yanglf007<br>
      Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>
    </div>
    <nav id="mobile-nav">
  
    <a href="/blog/" class="mobile-nav-link">Home</a>
  
    <a href="/blog/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>


  
<link rel="stylesheet" href="/blog/fancybox/jquery.fancybox.css">

  
<script src="/blog/fancybox/jquery.fancybox.pack.js"></script>




<script src="/blog/js/script.js"></script>




  </div>
</body>
</html>